/**
 * Licensed to the Apache Software Foundation （ASF） under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * （the "License"）； you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * <p>
 * https://www.q3z3.com
 * QQ : 939313737
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.platform.modules.sys.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.platform.common.web.service.impl.BaseServiceImpl;
import com.platform.common.exception.BaseException;
import com.platform.common.shiro.ShiroUtils;
import com.platform.modules.sys.dao.SysMenuDao;
import com.platform.modules.sys.dao.SysRoleMenuDao;
import com.platform.modules.sys.domain.SysMenu;
import com.platform.modules.sys.domain.SysUser;
import com.platform.modules.sys.service.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


/**
 * <p>
 * 系统菜单表 服务层实现
 * </p>
 */
@Service("sysMenuService")
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenu> implements SysMenuService {

    @Resource
    private SysMenuDao sysMenuDao;
    @Resource
    private SysRoleMenuDao sysRoleMenuDao;

    @Autowired
    public void setBaseDao() {
        super.setBaseDao(sysMenuDao);
    }

    @Override
    public List<Tree<Long>> tree(Long pid) {
        // 查询全部菜单
        List<SysMenu> sysMenuList = sysMenuDao.queryList(new SysMenu());
        if (CollectionUtils.isEmpty(sysMenuList)) {
            return new ArrayList<>();
        }
        sysMenuList = sysMenuList.stream().filter(menu -> !menu.getId().equals(pid)
                && menu.getType() == 1).collect(Collectors.toList());
        // 集合排序
        Collections.sort(sysMenuList, Comparator.comparing(SysMenu::getSort));
        // 定义返回值
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setParentIdKey("pid");
        treeNodeConfig.setNameKey("title");
        List<Tree<Long>> treeList = TreeUtil.build(sysMenuList, 0L, treeNodeConfig, (sysMenu, tree) -> {
            tree.setId(sysMenu.getId());
            tree.setParentId(sysMenu.getPid());
            tree.setName(sysMenu.getName());
        });
        return treeList;
    }

    @Override
    public List<Tree<Long>> menuTree() {
        // 获取当前用户
        SysUser sysUser = ShiroUtils.getUser();
        // 查询目录
        List<SysMenu> sysMenuList;
        if (ShiroUtils.isAdmin(sysUser)) {
            sysMenuList = sysMenuDao.queryList(new SysMenu(1));
        } else {
            sysMenuList = sysMenuDao.queryByRole(sysUser.getRoleId());
        }
        if (CollectionUtils.isEmpty(sysMenuList)) {
            return new ArrayList<>();
        }
        // 集合排序
        Collections.sort(sysMenuList, Comparator.comparing(SysMenu::getSort));
        // 定义返回值
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setNameKey("name");
        treeNodeConfig.setParentIdKey("pid");
        List<Tree<Long>> treeList = TreeUtil.build(sysMenuList, 0L, treeNodeConfig, (sysMenu, tree) -> {
            tree.setId(sysMenu.getId());
            tree.setParentId(sysMenu.getPid());
            tree.setName(sysMenu.getName());
            tree.putExtra("icon", sysMenu.getIcon());
            tree.putExtra("url", sysMenu.getUrl());
        });
        return treeList;
    }

    @Override
    public List<Long> queryByRoleId(Long roleId) {
        return sysRoleMenuDao.queryMenuIds(roleId);
    }

    @Override
    public List<String> queryRolePerms(Long roleId) {
        return sysMenuDao.queryRolePerms(roleId);
    }

    @Override
    public void deleteMenu(Long roleId) {
        SysMenu sysMenu = new SysMenu();
        sysMenu.setPid(roleId);
        Long count = queryCount(sysMenu);
        if (count > 0) {
            throw new BaseException("有下级菜单，不能删除");
        }
        this.deleteById(roleId);
    }

    private static AtomicInteger count;
    private static Long countId;

    @Transactional
    @Override
    public void copyMenu(Long menuId) {
        SysMenu sysMenu = getById(menuId);
        if (sysMenu == null) {
            throw new BaseException("菜单不存在");
        }
        count = new AtomicInteger(0);
        countId = DateUtil.currentSeconds();
        // 查询所有菜单
        List<SysMenu> menus = queryList(new SysMenu());
        // copy
        sysMenu.setId(getCopyCount());
        sysMenu.setName(sysMenu.getName() + "-copy");
        sysMenu.setSort(sysMenu.getSort() + 1);
        add(sysMenu);
        // 制作数结构
        List<Tree<Long>> treeList = buildCopyTree(menus, menuId);
        // copy
        doCopy(treeList, sysMenu.getId());
    }

    private Long getCopyCount() {
        return countId + count.incrementAndGet();
    }

    private void doCopy(List<Tree<Long>> treeList, Long parentId) {
        if (CollectionUtils.isEmpty(treeList)) {
            return;
        }
        for (Tree<Long> tree : treeList) {
            // copy
            SysMenu sysMenu = getById(tree.getId());
            Long menuId = getCopyCount();
            if (sysMenu != null) {
                sysMenu.setId(menuId);
                sysMenu.setPid(parentId);
                sysMenu.setName(sysMenu.getName() + "-copy");
                add(sysMenu);
            }
            // 递归
            List<Tree<Long>> children = tree.getChildren();
            if (!CollectionUtils.isEmpty(children)) {
                doCopy(children, menuId);
            }
        }
    }

    private List<Tree<Long>> buildCopyTree(List<SysMenu> menus, Long parentId) {
        if (CollectionUtils.isEmpty(menus)) {
            return null;
        }
        // 顺序排序
        Collections.sort(menus, Comparator.comparing(SysMenu::getSort));
        // 定义返回值
        List<Tree<Long>> treeList = TreeUtil.build(menus, parentId, (sysMenu, tree) -> {
            tree.setId(sysMenu.getId());
            tree.setParentId(sysMenu.getPid());
            tree.setName(sysMenu.getName());
        });
        return treeList;
    }


}
